#pragma once
#ifndef UTILS_H_
#define UTILS_H_

#include "mbv2.h"

template<
	unsigned N_BATCH,
	unsigned VEC_LEN
>
void load_ifm(data_stream<BIT_ACTV>& ifm, std::string path)
{
	ADT* ifm_buffer;
	ifm_buffer = (ADT*)malloc(VEC_LEN*sizeof(ADT));
	FILE *fp = fopen(path.c_str(), "rb");
	fread(ifm_buffer, 1, VEC_LEN*sizeof(ADT), fp);
	fclose(fp);

	for(size_t b=0; b < N_BATCH; b++)
	{
		for(size_t i=0; i < VEC_LEN; i++)
		{
			ifm.write(ifm_buffer[i]);
		}
	}
	free(ifm_buffer);
}

template<
	unsigned N_BATCH,
	unsigned VEC_LEN
>
int32_t check_cfm(axiu_stream<BIT_IO>& ofm, std::string path)
{
	ODT* ofm_buffer;
	ofm_buffer = (ODT*)malloc(VEC_LEN*sizeof(ODT));
	FILE *fp = fopen(path.c_str(), "rb");
	fread(ofm_buffer, 1, VEC_LEN*sizeof(ODT), fp);
	fclose(fp);

	ODT temp;
	int32_t compare;
	int32_t error_cnt = 0;
	for(size_t b=0; b < N_BATCH; b++)
	{
		for(size_t i=0; i < VEC_LEN; i++)
		{
			temp = ofm.read().data;
			if(abs(temp-ofm_buffer[i])>0)
			{
				std::cout << i << " wrong: " << (int32_t)temp << " " << ofm_buffer[i] << std::endl;
				error_cnt++;
			}
		}
	}
	free(ofm_buffer);
	return error_cnt;
}

template<
	unsigned N_BATCH,
	unsigned VEC_LEN
>
int32_t check_afm(data_stream<BIT_ACTV>& ofm, std::string path)
{
	uint8_t* ofm_buffer;
	ofm_buffer = (uint8_t*)malloc(VEC_LEN*sizeof(uint8_t));
	FILE *fp = fopen(path.c_str(), "rb");
	fread(ofm_buffer, 1, VEC_LEN*sizeof(uint8_t), fp);
	fclose(fp);

	ap_uint<BIT_ACTV> temp;
	uint8_t compare;
	int32_t error_cnt = 0;
	for(size_t b=0; b < N_BATCH; b++)
	{
		for(size_t i=0; i < VEC_LEN; i++)
		{
			temp = ofm.read();
			if(abs(temp-ofm_buffer[i])>4)
			{
				std::cout << i << " " << (int32_t)compare << " " << (int32_t)ofm_buffer[i] << std::endl;
				error_cnt++;
			}
		}
	}
	free(ofm_buffer);
	return error_cnt;
}
#endif
